// Copyright (c) Appeon. All rights reserved.
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. 
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.

using System;
using System.Collections.Generic;

namespace SnapObjects.Data
{
    internal class DynamicModelFactory : IModelFactory<DynamicModel>
    {
        private readonly DynamicModelAccessor _dynamicModelAccessor;

        public DynamicModelFactory(IDictionary<string, Type> properties)
        {
            this.ModelMeta = this.CreateModelMeta(properties);

            this.DynamicModelBaseFactory = new DynamicModelBaseFactory(this.ModelMeta);

            _dynamicModelAccessor = this.CreateModelAccessor();
        }

        public DynamicModelFactory(IDictionary<string, DbColumnInfo> properties)
        {
            this.ModelMeta = this.CreateModelMeta(properties);

            this.DynamicModelBaseFactory = new DynamicModelBaseFactory(this.ModelMeta);

            _dynamicModelAccessor = this.CreateModelAccessor();
        }

        public DynamicModel Create()
        {
            var model = this.DynamicModelBaseFactory.Create();

            var dynamicModel = new DynamicModel(
                model, this.DynamicModelBaseFactory.GetAccessor(), this);

            return dynamicModel;
        }

        public DynamicModelBaseFactory DynamicModelBaseFactory { get; }

        public DynamicModelMeta ModelMeta { get; }

        public IModelAccessor<DynamicModel> GetAccessor()
        {
            return _dynamicModelAccessor;
        }

        public IModelValidator<DynamicModel> GetValidator()
        {
            return new DynamicModelValidator();
        }

        protected virtual DynamicModelAccessor CreateModelAccessor()
        {
            return new DynamicModelAccessor(this);
        }

        protected virtual DynamicModelMeta CreateModelMeta(IDictionary<string, Type> properties)
        {
            return new DynamicModelMeta(properties);
        }

        protected virtual DynamicModelMeta CreateModelMeta(IDictionary<string, DbColumnInfo> properties)
        {
            return new DynamicModelMeta(properties);
        }
    }
}
